/***************************************************
> Copyright (C) 2024 ==KINGYI== All rights reserved.
> File Name: server.c
> Author:cjy
> Mail: 
> Created Time: 2024年08月15日 星期四 15时21分58秒
***************************************************/
// 开发一个多进程计算服务器
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include "cJSON.h"

struct data {
    int type;
    char count[10];
    float num1;
    float num2;
};

struct number {
    float sum;
};

int main(int argc, const char* argv[]) {

    int sock = 0;
    int listenfd = 0;
    int ret = 0;
    int max_fd = 0; 

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("socket");
        exit(-1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(6661);
    addr.sin_addr.s_addr = inet_addr("192.168.198.128");

    ret = bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    if (ret == -1) {
        perror("bind");
        exit(-1);
    }

    listen(sock, 5);
    max_fd = sock; 

    
    fd_set readfds;
    FD_ZERO(&readfds); 
    FD_SET(sock, &readfds); 

    struct timeval timeout;
    timeout.tv_sec = 1; 
    timeout.tv_usec = 0; 

    while (1) {
        
        fd_set tmpfds = readfds;

        ret = select(max_fd + 1, &tmpfds, NULL, NULL, &timeout);
        if (ret == -1) {
            perror("select");
            continue;
        } else if (ret == 0) {
            
            continue;
        }

        
        if (FD_ISSET(sock, &tmpfds)) {
            listenfd = accept(sock, NULL, NULL);
            if (listenfd == -1) {
                perror("accept");
                continue;
            }
            FD_SET(listenfd, &readfds); 
            if (listenfd > max_fd) {
                max_fd = listenfd; 
            }
            printf("New client connected: %d\n", listenfd);
        }

        
        for (int i = 0; i <= max_fd; i++) {
            if (FD_ISSET(i, &tmpfds)) {
                if (i != sock) { 
                    char buf[1024] = {0};
                    ret = recv(i, buf, sizeof(buf) - 1, 0);
                    if (ret == -1) {
                        if (errno == ECONNRESET) {
                            printf("Client disconnected: %d\n", i);
                            close(i);
                            FD_CLR(i, &readfds); 
                        }
                        continue;
                    } else if (ret == 0) {
                        printf("Client disconnected: %d\n", i);
                        close(i);
                        FD_CLR(i, &readfds); 
                        continue;
                    }

                    puts(buf);

                    cJSON *json = cJSON_Parse(buf);
                    struct data dat;
                    memset(&dat, 0, sizeof(dat));

                    struct number num;
                    memset(&num, 0, sizeof(num));

                    cJSON *node = cJSON_GetObjectItem(json, "type");
                    if (node && node->type == cJSON_Number) {
                        dat.type = node->valueint;
                    }

                    node = cJSON_GetObjectItem(json, "count");
                    if (node && node->type == cJSON_String) {
                        strcpy(dat.count, node->valuestring);
                    }

                    node = cJSON_GetObjectItem(json, "num1");
                    if (node && node->type == cJSON_Number) {
                        dat.num1 = node->valuedouble;
                    }

                    node = cJSON_GetObjectItem(json, "num2");
                    if (node && node->type == cJSON_Number) {
                        dat.num2 = node->valuedouble;
                    }

                    if (dat.type == 1) {
                        num.sum = dat.num1 + dat.num2;
                    } else if (dat.type == 2) {
                        num.sum = dat.num1 - dat.num2;
                    } else if (dat.type == 3) {
                        num.sum = dat.num1 * dat.num2;
                    } else if (dat.type == 4) {
                        num.sum = dat.num1 / dat.num2;
                    }

                    json = cJSON_CreateObject();
                    cJSON_AddItemToObject(json, "sum", cJSON_CreateNumber(num.sum));

                    char *dest = cJSON_Print(json);

                    ret = send(i, dest, strlen(dest), 0);
                    if (ret == -1) {
                        perror("send");
                        continue;
                    }

                    cJSON_Delete(json);
                }
            }
        }
    }

    close(sock);

    return 0;
}

